package com.ts.api.module.api.service.impl;

import com.gitee.apanlh.util.algorithm.digest.MD5;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;
import com.ts.api.common.constant.api.ApiApplyQueryStatusEnum;
import com.ts.api.common.constant.api.ApiBizTypeEnum;
import com.ts.api.common.constant.api.ApiEnum;
import com.ts.api.common.constant.productflow.ProductApplyFlowStatusEnum;
import com.ts.api.common.redis.ApiMatchPhoneMaskRedisKey;
import com.ts.api.common.redis.entity.ApiMatchPhoneMaskRedisCache;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiBizMatchBO;
import com.ts.api.module.api.entity.bo.ApiDataExchangeBO;
import com.ts.api.module.api.entity.bo.ApiParameterBO;
import com.ts.api.module.api.entity.bo.ApiPhoneMaskDataExchangeBO;
import com.ts.api.module.api.entity.bo.ApiPreRequiredBO;
import com.ts.api.module.api.entity.bo.ApiRequiredFlowBO;
import com.ts.api.module.api.entity.po.ApiKeyPO;
import com.ts.api.module.api.entity.vo.ReqApiParameterVO;
import com.ts.api.module.api.entity.vo.RespApiApplyQueryVO;
import com.ts.api.module.api.entity.vo.RespV3ApiDataExchangePhoneMaskVO;
import com.ts.api.module.api.entity.vo.RespV3ApiDataExchangeVO;
import com.ts.api.module.api.service.ApiBizApplyService;
import com.ts.api.module.api.service.ApiBizDataExchangeService;
import com.ts.api.module.api.service.ApiBizMultiPushService;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.api.service.ApiMsgV3Service;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeField;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributePhoneMaskField;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.qo.ProductApplyFlowQO;
import com.ts.api.module.product.service.ProductApplyFlowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;


@Service
public class ApiMsgV3ServiceImpl implements ApiMsgV3Service {

    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private ApiBizDataExchangeService apiBizDataExchangeService;
    @Autowired
    private ApiBizMultiPushService apiBizMultiPushService;
    @Autowired
    private ApiBizApplyService apiBizApplyService;
    @Autowired
    private ProductApplyFlowService productApplyFlowService;

    @Override
    public RespV3ApiDataExchangeVO dataExchange(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO) throws Exception {
        //  1.前置撞库校验-普通类型计划模式
        ApiBizMatchBO normalPlan = ApiBizMatchBO.createNormalPlan(true);
        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.DATA_EXCHANGE, null, normalPlan);
        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParam(apiPreRequiredBO);

        //  2.撞库匹配
        ApiDataExchangeBO apiDataExchangeBO = apiBizDataExchangeService.dataExchange(apiParameterBO);

        //  3.返回撞库消息
        PlanDistributeField planDistributeField = apiDataExchangeBO.getPlanDistributeField();
        RespV3ApiDataExchangeVO respV3ApiDataExchangeVO = RespV3ApiDataExchangeVO.of(planDistributeField);
        return respV3ApiDataExchangeVO;
    }

    @Override
    public void apply(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO) {
        //  1.查询是否渠道存在该流程
        ApiUserRequest apiUserRequest = reqApiParameterVO.getApiUserRequest();
        String phone = apiUserRequest.getPhone();
        Assert.isNotEmptyThrows(phone, new ApiMsgException(ApiEnum.API_REQUIRED_PARAM_NULL.format("phone")));
        String phoneMd5 = MD5.create().digestToHex(phone);

        ApiRequiredFlowBO apiRequiredFlowBO = ApiRequiredFlowBO.createByApiClientId(phoneMd5, apiKeyPO.getApiClientId());
        ProductApplyFlowPO productApplyFlowPO = apiBizRequiredService.requiredSucDataExchangeFlow(apiRequiredFlowBO);
        Assert.isNotNullThrows(productApplyFlowPO, new ApiMsgException(ApiEnum.API_APPLY_FLOW_ERROR));

        //  2.进件-前置参数验证
        ApiBizMatchBO normalPlanApply = ApiBizMatchBO.createNormalPlanApply();
        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.APPLY, null, normalPlanApply);
        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParam(apiPreRequiredBO);

        //  3.多推全流程
        apiBizMultiPushService.multiApply(apiUserRequest, apiParameterBO, productApplyFlowPO);

        //  3.全流程进件流程
        apiBizApplyService.apply(apiUserRequest, apiParameterBO, productApplyFlowPO);
    }

    @Override
    public RespApiApplyQueryVO applyStatusQuery(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO) {
        Map<String, String> formMap = reqApiParameterVO.getFormMap();

        String phoneMd5 = formMap.get("applyId");
        Assert.isNotEmptyThrows(phoneMd5, new ApiMsgException(ApiEnum.API_REQUIRED_PARAM_NULL.format("applyId")));

        //  默认返回进件等待状态
        RespApiApplyQueryVO respApplyQueryVO = RespApiApplyQueryVO.create(phoneMd5, ApiApplyQueryStatusEnum.AWAIT);

        //  查询进件状态
        ProductApplyFlowQO productApplyFlowQO = new ProductApplyFlowQO();
        productApplyFlowQO.setApiClientId(apiKeyPO.getApiClientId());
        productApplyFlowQO.setPhoneMd5(phoneMd5);
        productApplyFlowQO.setApiEnvType(apiKeyPO.getApiEnvType());
        List<ProductApplyFlowPO> listProductApplyFlowPO = productApplyFlowService.list(productApplyFlowQO);

        //  分组转换流程状态
        Map<Integer, List<ProductApplyFlowPO>> flowMap = CollUtils.groupBy(listProductApplyFlowPO, ProductApplyFlowPO::getStatus);

        //  是否存在授权节点
        if (ValidParam.isNotEmpty(flowMap.get(ProductApplyFlowStatusEnum.USER_ACCEPT.getType()))) {
            respApplyQueryVO = RespApiApplyQueryVO.create(phoneMd5, ApiApplyQueryStatusEnum.SUC);
        }
        //  存在进件失败
        if (ValidParam.isNotEmpty(flowMap.get(ProductApplyFlowStatusEnum.APPLY_ERROR.getType()))) {
            respApplyQueryVO = RespApiApplyQueryVO.create(phoneMd5, ApiApplyQueryStatusEnum.FAIL);
        }
        //  我方业务校验失败
        if (ValidParam.isNotEmpty(flowMap.get(ProductApplyFlowStatusEnum.APPLY_BIZ_ERROR.getType()))) {
            respApplyQueryVO = RespApiApplyQueryVO.create(phoneMd5, ApiApplyQueryStatusEnum.FAIL);
        }
        return respApplyQueryVO;
    }

    @Override
    public RespV3ApiDataExchangePhoneMaskVO dataExchangePhoneMask(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO, Integer maskLen) throws Exception {
        //  1.前置撞库校验-普通类型计划模式
        ApiBizMatchBO normalPlan = ApiBizMatchBO.createNormalPlan(true);
        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.DATA_EXCHANGE, null, normalPlan);
        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParamPhoneMask(apiPreRequiredBO);

        //  2.撞库匹配
        ApiPhoneMaskDataExchangeBO apiPhoneMaskDataExchangeBO = apiBizDataExchangeService.dataExchangePhoneMask(apiParameterBO, maskLen);

        //  3.返回撞库消息
        String reqId = apiPhoneMaskDataExchangeBO.getReqId();
        List<PlanDistributePhoneMaskField> listPhoneMaskField = apiPhoneMaskDataExchangeBO.getListPhoneMaskField();
        return RespV3ApiDataExchangePhoneMaskVO.of(reqId, listPhoneMaskField);
    }

    @Override
    public void applyPhoneMask(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO, Integer maskLen) {
        String apiClientId = apiKeyPO.getApiClientId();

        //  1.获取撞库时保存的唯一请求id
        ApiUserRequest apiUserRequest = reqApiParameterVO.getApiUserRequest();
        String applyId = apiUserRequest.getApplyId();
        Assert.isNotEmptyThrows(applyId, new ApiMsgException(ApiEnum.API_RECEIVE_BODY_MISS.format("applyId")));

        //  2.根据applyId获取可进件的机构号
        Long loanChannelId = apiKeyPO.getLoanChannelId();
        String saveDataExchangeKey = ApiMatchPhoneMaskRedisKey.getApiChannelDataExchangeReqIdKey(loanChannelId, applyId);
        ApiMatchPhoneMaskRedisCache apiMatchPhoneMaskRedisCache = ApiMatchPhoneMaskRedisKey.API_CHANNEL_DATA_EXCHANGE_PHONE_MASK_APPLY_ID.get(saveDataExchangeKey, ApiMatchPhoneMaskRedisCache.class);
        Assert.isNotNullThrows(apiMatchPhoneMaskRedisCache, new ApiMsgException(ApiEnum.API_APPLY_ID_ERROR));

        //  3.查询是否渠道存在该流程-apiClientId + productPlanId + dataExchangeReqId
        Long productPlanId = apiMatchPhoneMaskRedisCache.getProductPlanId();
        String dataExchangeReqId = apiMatchPhoneMaskRedisCache.getDataExchangeReqId();
        ApiRequiredFlowBO apiRequiredFlowBO = ApiRequiredFlowBO.createPhoneMaskFlow(apiClientId, productPlanId, dataExchangeReqId);
        ProductApplyFlowPO productApplyFlowPO = apiBizRequiredService.requiredSucDataExchangeFlow(apiRequiredFlowBO);
        Assert.isNotNullThrows(productApplyFlowPO, new ApiMsgException(ApiEnum.API_APPLY_FLOW_ERROR));

        //  4.进件-前置参数验证
        ApiBizMatchBO normalPlanApply = ApiBizMatchBO.createNormalPlanApply();
        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.APPLY, null, normalPlanApply);
        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParamPhoneMask(apiPreRequiredBO);

        //  5.全流程进件流程
        apiBizApplyService.applyPhoneMask(apiUserRequest, apiParameterBO, productApplyFlowPO);
    }
}
